package com.tn.rtdata.examples.stockticker.server;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tn.rtdata.examples.stockticker.StockTick;
import com.tn.rtdata.examples.stockticker.server.fill.StockTickFill;
import com.tn.rtdata.examples.stockticker.server.util.ConcurrentObservableMap;

/**
 * An implementation of <code>Runnable</code> that randomly adjusts the price of a <code>StockTick</code>.
 */
public class StockTicker
{
  private static final Logger LOGGER = LoggerFactory.getLogger(StockTickFill.class);

  private Map<String, StockTick> stockTickCache;
  private BigDecimal maximumMovement;
  private boolean running;
  private Random random;

  /**
   * Creates a new <code>StockTicker</code> initialized with the <code>maximumMovement</code>.
   */
  public StockTicker(Map<String, StockTick> stockTickCache, BigDecimal maximumMovement)
  {
    this.stockTickCache = stockTickCache;
    this.maximumMovement = maximumMovement;
    this.random = new Random();
  }

  /**
   * Starts the stock ticker.
   */
  public void start()
  {
    this.running = true;
    Thread tickerThread = new Thread(new Ticker(), "stock-ticker");
    tickerThread.setDaemon(true);
    tickerThread.start();
  }

  /**
   * Stops the stock ticker.
   */
  public void stop()
  {
    this.running = false;
  }

  /**
   * An implementation of <code>Runnable</code> that randomly ticks stocks in the stock tick cache.
   */
  private class Ticker implements Runnable
  {
    /**
     * {@inheritDoc}
     */
    @Override
    public void run()
    {
      while (running)
      {
        try
        {
          Thread.sleep(1000);

          List<String> stockIds = new ArrayList<String>(stockTickCache.keySet());

          if (stockTickCache.size() > 0)
          {

            Double randomIndex = Math.random() * (stockIds.size() - 1);

            if (random.nextBoolean())
            {
              StockTick stockTick = stockTickCache.get(stockIds.get(randomIndex.intValue()));
              if (stockTick != null)
              {
                stockTickCache.put(stockTick.getStockId(), stockTick.movePrice(maximumMovement));
              }
            }
          }
        }
        catch (Exception e)
        {
          LOGGER.error("An error occurred ticking stock.", e);
        }
      }
    }
  }
}
